Skip to content

fix(gate): the online gate has no key for the nvidia 27B, and a skipped model gate records as passed - #229

Merged
localai-bot merged 1 commit into
mainfrom
row/GATE-SERVER-BINARY
Aug 10, 2026
Merged

fix(gate): the online gate has no key for the nvidia 27B, and a skipped model gate records as passed#229
localai-bot merged 1 commit into
mainfrom
row/GATE-SERVER-BINARY

Conversation

@localai-bot

@localai-bot localai-bot commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Closes #222. The reproducible measurement path for #213.

What changed since review

This PR was reviewed MERGE at 0157a1e2 and then stopped merging: two commits
landed on main while it was in review and did the same path repair.

on main in this PR
examples/serverexamples/vllm-server path repair YES (2b262622, 8fce04d3) dropped — superseded
model key 27n no yes
drift guard (tests/tools/test_online_gate_server_binary.py) no yes
fail-closed model gate no yes

The rename repair is gone from this branch. main's version is kept
verbatim — it is not re-landed, not reverted, and not reworded. The remaining
three contributions are what main's repair did not do.

1. A model key for nvidia/Qwen3.6-27B-NVFP4 (27n)

The harness had keys for the unsloth 27B, the nvidia 35B and the MXFP4 8B, but
none for the checkpoint the parity campaign targets and every recorded 0.85x
number was taken on. Without a key, that model can only be benched by an ad-hoc
harness enforcing none of the pinned revision, oracle inventory, cache-drop or
one-lock checks, so its numbers can never become accepted evidence. 27n
@0893e160 is wired through MODEL_REVISIONS, MODEL_REPOSITORIES,
MAX_NUM_BATCHED_TOKENS (2048, dense), MAX_MODEL_LEN, the shell --model
guard, the batched-token branch and the correctness-gate dispatch.

27 and 27n are different models, not two spellings: different lm_head
dtype, different mixed-precision layout, no shared goldens, non-comparable
ratios. --trace-only refuses 27n and now says WHY — the node counts in
TRACE_PRIMARY_GRAPH_CONTRACTS were captured on @890bdef7 alone, so the
refusal is about which checkpoint, not which architecture.

2. A fail-closed model gate

tests/parity/test_qwen27_paged_engine.cpp emits a loud MESSAGE and returns 0
when its snapshot is absent, so ctest exit 0 said nothing about whether a
token was compared — and record-model-gate wrote "passed": true regardless.
On a box holding @0893e160 but not @890bdef7 — the expected shape for
27n — that produced preflight/model-gate/27n.json marked passed with zero
tokens compared.

  • MODEL_GATE_CONTRACTS pins each dispatchable gate's proof line and the
    checkpoint its committed goldens belong to.
  • record-model-gate refuses with "compared no token" unless the log carries
    that line, and refuses a test_name with no contract at all.
  • the driver runs ctest -V, so a passing run's own output reaches the log
    (--output-on-failure prints nothing for a pass).
  • golden_revision, model_revision and golden_covers_benched_checkpoint
    (deliberately false for 27n, whose precondition is build sanity on a
    neighbour's goldens) are written to the evidence and revalidated by the
    summary. A shell comment reaches neither the evidence nor a reader of the
    summary.

The earlier review tried eight ways to make this pass vacuously and failed each
time; that property was re-verified after the rebase (see Verification).

3. The drift guard, adapted to main's form

tests/tools/test_online_gate_server_binary.py parses examples/CMakeLists.txt
for OUTPUT_NAME rather than hardcoding a spelling, and SCANS the live surfaces
for the stale path rather than naming files it already knows about — naming
files is how #222's first repair missed the whole Python half, and how its
second still left three live sites.

main fixed the paths differently, and the guard now describes that reality
rather than forcing this branch's form.
main does not hardcode the new name:
it resolves examples/<OUTPUT_NAME> and keeps examples/server as a REPLAY
FALLBACK so a pre-W6 evidence tree still replays against the binary it was
recorded with. The guard's original line-level rejection would have failed
against that. It now admits the fallback by shape (FALLBACK_PATTERNS), and
only in a file that resolves the declared name too — so:

  • a fallback whose primary is deleted is an ordinary hardcode and is reported;
  • a fresh hardcode sitting beside a primary is still reported, i.e. "this file
    mentions the new name" can never launder an occurrence;
  • gdn_packed_component.py's server.name not in ("vllm-server", "server")
    needs no exemption — it admits both names, so it never matches at all, while a
    regression to != "server" still does.

Two cases were added for this: one proving those three properties, and one
proving the fallback is actually present in all three drivers, so silently
dropping pre-W6 replay cannot go unnoticed.

docs/USAGE.md's H3-over-HTTP quick start is repaired here. README.md is not:
check-doc-checkpoint.py refuses any README change whose commit does not also
touch a landing source, and examples/CMakeLists.txt — the file that decides
the name — is not on that list. Recorded as one named file in
SCAN_BLOCKED_ON_POLICY, with a test that the debt can neither grow nor outlive
itself, awaiting the decision 4f24ff44 made for this exact class.

Incidental: main is currently red

2b262622 left test_trace_driver_builds_before_requiring_the_server_binary
failing on main — it anchors on [[ -x ${build_dir}/examples/server ]], the
line that repair replaced with the server_bin resolution. Re-anchored here on
the resolution line, which is what the ordering assertion is actually about.

The self-inflicted regression this PR originally caught — record-execution
writing examples/vllm-server while gdn_packed_component.py:1559 required
basename server — was re-checked against main's version and does not
recur
: 8fce04d3 widened that check to accept both names.

Verification (all CPU/Python)

result
python3 -m unittest discover -s tests/tools -t . on main 187 tests, 1 error (main is red, see above)
same, on this branch 208 tests, OK
scripts/agent-preflight.sh / --staged exit 0
scripts/check-pr-size.py --base origin/main OK — 898/900 product lines
scripts/check-doc-checkpoint.py OK

208 = 187 + 19 (the guard's 18 cases + 1 summary case) + 2 (the two new
fallback cases) — with main's one error fixed.

Mutation battery. 14 mutations of the claimed guarantees, each applied to a
scratch copy of this head: the shell fallback reduced to a plain hardcode; the
Python primary deleted; the gdn basename check regressed to != "server"; -V
removed; 27n dropped from MODEL_REVISIONS; 27n dropped from the shell
guard; the proof-line check neutered; docs/USAGE.md re-staled; 27n falling
through to the no-golden else-arm; golden_covers_benched_checkpoint hardcoded
True; the summary's scope revalidation removed; the trace-only refusal losing
the checkpoint name; a proof marker reworded; SCAN_BLOCKED_ON_POLICY widened
to a second file. All 14 turn the suite red; the restored tree is green.

Conflict resolution, per file:

file resolution
tools/bench/online_gate.py main's server_binary() helper and its 3 call sites kept verbatim; 27n + MODEL_GATE_CONTRACTS + record_model_gate reapplied on top
scripts/dgx-online-serving.sh main's server_bin resolution kept verbatim; the five 27n/ctest -V edits reapplied on top
tools/bench/gdn_packed_component.py main's version taken wholesale; this branch's change dropped
scripts/dgx-gdn-packed-component.sh main's version taken wholesale; this branch's change dropped
tools/bench/run_serve_low.py main already has it; dropped
.agents/roadmap_v1.md keyed record — main's version taken wholesale, the #222 row reapplied (no #213 row present to collide with)
docs/USAGE.md main's version taken wholesale, the one quick-start line reapplied

🤖 Generated with Claude Code

@localai-bot
localai-bot force-pushed the row/GATE-SERVER-BINARY branch from f7189aa to 0157a1e Compare August 10, 2026 08:09
localai-bot pushed a commit that referenced this pull request Aug 10, 2026
…, and make a model gate prove it ran

Review of #229 (issue #222) returned CHANGES-REQUIRED. The examples/vllm-server
repair and its CMake-parsing drift guard were confirmed correct; the 27n half was
not. This resolves the findings.

F1 -- the two shell-side 27n assertions had ZERO effective coverage. Each was a
substring satisfied by the OTHER line: `${model} == 27n` occurs inside the
--model guard, and `${model} == 27 || ${model} == 27n` occurs inside the
test_name dispatch. Proven RED-free both ways on the shipped tests: reverting
:243 to `27` only left 8/8 GREEN while 27n fell through to the else-arm
(test_name=mxfp4_smoke_battery, gate_target=vllm-cli -- benched with no golden,
verbatim what the docstring claims to prevent), and dropping 27n from the guard
also left 8/8 GREEN. Both assertions now PARSE the driver: accepted_model_keys()
reads the guard LINE and requires set equality with MODEL_REVISIONS, and
correctness_gate_by_model_key() replays the if/elif/else chain and asserts the
whole key->test_name mapping. Re-verified: mutation A now fails with
'test_qwen27_paged_engine' != 'mxfp4_smoke_battery', mutation B with "27n not
found in frozenset({'q3mxfp4','27','35'})".

F2 -- `if __name__ == "__main__"` sat BEFORE the second class, so
`python3 tests/tools/test_online_gate_server_binary.py` ran 4 of 8 and printed
OK. Moved to the end. The module's sibling convention imports tools.bench at
module scope, so REPO_ROOT joins sys.path or the direct invocation would now die
on ImportError instead of under-running.

F3 -- the same defect was unfixed in a sibling driver, and the guard could not
see it because it hardcoded two file paths. It now SCANS the live surfaces
(scripts, tools, tests, examples, src, include, docs, cmake, release, docker,
.github, README, root CMakeLists) for three shapes: a path component in front of
examples/server, pathlib's "examples" / "server", and a BASENAME check against
"server". That last shape found a site nobody had listed: PR #229 made
online_gate.py record-execution write examples/vllm-server while
gdn_packed_component.py:1559 still required `server.name != "server"` -- so the
component driver rejected the manifest the shared harness had just written for
it. Seven live sites fixed: dgx-gdn-packed-component.sh x3 (including the live
server command array), gdn_packed_component.py, its fixture,
run_serve_low.py's recipe manifest and docs/USAGE.md.

NEEDS_DECISION -- README.md:168 and :368 are NOT fixed here and remain user-
visible. scripts/check-doc-checkpoint.py refuses any README change whose commit
does not also touch a landing source, and the file that decides the name the
quick start tells a user to type -- examples/CMakeLists.txt OUTPUT_NAME -- is not
on that list, while examples/{cli,server}/main.cpp are. This change has no honest
reason to edit a listed file; manufacturing a cosmetic edit to one, or relaxing
the checker, would both be weakening a gate to make a change pass. `4f24ff44`
recorded this exact class ("a gate that rejects a true statement is not
protecting anything") and repaired it by adding a REAL source to the list. The
same decision is owed here. The scan therefore carries README in a one-file
SCAN_BLOCKED_ON_POLICY set that names the blocker, guarded by a case asserting
the set holds exactly that file AND that the debt still exists -- so the
exclusion cannot outlive it or quietly grow.

.agents/ and benchmarks/ are deliberately NOT scanned: they quote the command a
past campaign actually ran, and rewriting them would falsify evidence rather
than repair a consumer. scripts/dgx-online-serving.sh's `build_targets=(server)`
is correct and untouched -- that is the CMake TARGET name.

F4 -- the documented no-OUTPUT_NAME fallback was unsatisfiable: it demanded
'"examples" / "server"' present AND absent. Removing the override and setting
both harnesses to examples/server (correct for that world) yielded 2 red with
the self-refuting message "still resolves the server as examples/server ...; the
build emits examples/server". The stale-spelling assertion is now skipped when
the target name IS the output name.

F5 -- the 27n correctness precondition could pass VACUOUSLY and nothing recorded
it. test_qwen27_paged_engine emits a MESSAGE and returns 0 when the UNSLOTH
snapshot is absent; record_model_gate then wrote "passed": true unconditionally.
A box with @0893e160 but not @890bdef7 -- the EXPECTED shape for a key whose
whole point is a different checkpoint -- produced 27n.json marked passed with
zero tokens compared. Now MODEL_GATE_CONTRACTS carries, per dispatched gate, the
proof line it prints only after comparing tokens and the revision its committed
goldens belong to. record_model_gate fails closed without the proof line and
records golden_revision, model_revision and golden_covers_benched_checkpoint
(deliberately false for 27n); the driver runs ctest -V so a PASSING run's output
reaches the log at all; and the summary revalidates all of it. Two drift guards
parse the markers out of the gates' own sources and the revision out of
hf_snapshot.h, so a reworded MESSAGE fails here rather than silently disarming
the check.

F6 -- #222 added to the roadmap issue table, and the 27n key, its pinned
revision, its build-sanity-only scope and its stop condition recorded in the
EXISTING cuda-online-serving-gate spec. No new row.

F7 -- the trace-only refusal said "defined only for the Qwen3.6-27B dense
graph", which 27n IS. It now names the checkpoint whose graph contracts were
captured.

F8 noted, no action: 27n widens the cross-model summary default exactly as
q3mxfp4 already does; not newly broken.

Fixtures in test_online_gate_summary.py and test_online_gate_client.py are
re-derived from the real gate log shape (they carried "passed\n"), not relaxed.

GATES: 18 modules under tests/tools, 206 tests, GREEN (195 before; 11 new cases,
every one shown red first). scripts/agent-preflight.sh exits 0.

Refs #222, #213

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
@localai-bot
localai-bot force-pushed the row/GATE-SERVER-BINARY branch from 0157a1e to f09d16a Compare August 10, 2026 13:43
@localai-bot localai-bot changed the title fix(gate): online-serving harness consumes examples/vllm-server; add the nvidia 27B key fix(gate): the online gate has no key for the nvidia 27B, and a skipped model gate records as passed Aug 10, 2026
…ped model gate records as passed (#222)

`main` already repaired the `examples/server` -> `examples/vllm-server` path
(2b26262, 8fce04d), so this no longer carries that fix. What it carries is the
three things that repair did not:

**A model key for `nvidia/Qwen3.6-27B-NVFP4`.** The harness had keys for the
unsloth 27B, the nvidia 35B and the MXFP4 8B, but none for the checkpoint the
parity campaign targets and every recorded 0.85x number was taken on. Without a
key that model can only be benched by an ad-hoc harness enforcing none of the
pinned revision, oracle inventory, cache-drop or one-lock checks, so its numbers
can never become accepted evidence. Key `27n` @0893e160 closes that -- it is the
reproducible recipe #213's headline model otherwise has none of. `27` and `27n`
are DIFFERENT models, not two spellings: different lm_head dtype, different
mixed-precision layout, no shared goldens, non-comparable ratios.

**A fail-closed model gate.** `tests/parity/test_qwen27_paged_engine.cpp` emits a
loud MESSAGE and returns 0 when its snapshot is absent, so ctest exit 0 said
nothing about whether a token was compared -- and `record-model-gate` wrote
`"passed": true` regardless. On a box holding @0893e160 but not @890bdef7, the
EXPECTED shape for `27n`, that produced a model gate marked passed with zero
tokens compared. Now: `MODEL_GATE_CONTRACTS` pins each gate's proof line and the
checkpoint its committed goldens belong to; `record-model-gate` refuses with
"compared no token" unless the log carries that line; the driver runs `ctest -V`
so a PASSING run's output actually reaches the log; and `golden_revision`,
`model_revision` and `golden_covers_benched_checkpoint` (deliberately `false`
for `27n` -- its precondition is build sanity on a neighbour's goldens) are
written to the evidence and revalidated by the summary. A prose comment reaches
neither the evidence nor a reader of the summary.

**A drift guard**, `tests/tools/test_online_gate_server_binary.py`. It parses
`examples/CMakeLists.txt` for `OUTPUT_NAME` rather than hardcoding a spelling,
and SCANS the live surfaces for the stale path rather than naming the files it
already knows about -- naming files is how #222's first repair missed the whole
Python half and its second still left `docs/USAGE.md` and two README quick
starts pointing at a binary the build has not produced since W6.

`main`'s repair resolves the declared name and keeps `examples/server` as a
REPLAY fallback, so a pre-W6 evidence tree still replays. The guard describes
that reality instead of forcing this branch's hardcoded form: `FALLBACK_PATTERNS`
admits the fallback SHAPE, and only in a file that resolves the declared name
too -- a fallback whose primary is deleted is an ordinary hardcode and is
reported again, and a fresh hardcode beside a primary is never laundered.

`docs/USAGE.md`'s H3-over-HTTP quick start is repaired here. README.md is not:
`check-doc-checkpoint.py` refuses any README change whose commit does not also
touch a landing source, and `examples/CMakeLists.txt` -- the file that decides
the name -- is not on that list. Recorded as one named file in
`SCAN_BLOCKED_ON_POLICY`, with a test that the debt cannot grow or outlive
itself, awaiting the same decision `4f24ff44` made for that class.

Also fixes `test_trace_driver_builds_before_requiring_the_server_binary`, which
2b26262 left red on main: it anchored on `[[ -x ${build_dir}/examples/server ]]`,
a line that repair replaced with the `server_bin` resolution.

tests/tools: 208 pass (main: 187 with 1 error). 14 mutations of the claimed
guarantees each turn the suite red.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
@localai-bot
localai-bot force-pushed the row/GATE-SERVER-BINARY branch from f09d16a to a7bb944 Compare August 10, 2026 13:49
@localai-bot
localai-bot merged commit f86e4cc into main Aug 10, 2026
11 of 14 checks passed
localai-bot pushed a commit that referenced this pull request Aug 10, 2026
…o four decimals

First measurement of nvidia/Qwen3.6-27B-NVFP4 @0893e160 through a reproducible
recipe. Every prior number for it came from an ad-hoc harness, because the
canonical gate could not start a server (#222) and there was no model key for it
until #229 added 27n.

vllm.cpp 9ff2742e; oracle pip vLLM 0.25.0 + FlashInfer 0.6.13 in its PRODUCTION
GRAPHED configuration, never --enforce-eager. Build guards confirmed present:
FlashAttention-2 ENABLED for [121a], VLLM_CPP_TRITON resolved ON with real
sm_121a AOT variants. Idle box, medians of 3, drop_caches between legs, noise
band measured BEFORE any delta was read.

c1 0.8289x, c2 0.8461x, c4 0.8529x, c8 0.8639x. This CONFIRMS the previously
recorded 0.843-0.861x band, so the ad-hoc numbers were not wrong; they are kept
as a superseded row rather than deleted.

The step is now attributed. A decode-only nsys two-length diff with
--cuda-graph-trace=node, BOTH arms in the same tool, node-level tracing proven by
integral launch counts and two capture pairs agreeing to 0.005%:

  +8.6414 lm_head/Marlin  +7.6068 fp8 tower  +0.0532 splitK  +1.0279 other
  = 17.3292 ms/step   vs measured 17.3292

At 99.2/99.3% GPU-busy the c1 step is GPU-bound on both arms, so the whole gap is
kernel time: no host, scheduler or launch-overhead lever exists here. Both levers
are TRAFFIC/FUSION, not kernel quality. Our Marlin reaches 207.9 GiB/s against
vLLM's 210.0 on the same combined shape, and both arms read identical fp8 bytes;
we simply move more of them, and issue 96 GDN input GEMMs where vLLM issues 48
merged qkvz.

Recorded honestly rather than flatteringly: RSS is 1.612x and BELOW FLOOR,
c16/c32 are NOT MEASURED (one attempt lost the denominator to a foreign build
contending mid-timing, the other to a host OOM-reboot), GPU memory is PENDING
because the instrument returns N/A on this unified part, and our c1 ratio is
host-memory-state sensitive in a way vLLM's is not (0.7604 vs 0.8289 across a
reboot, protocols also differing, variables not separated).

Startup is the one axis we win outright: 33.38 s vs 182.41 s, 5.46x faster.

Written as table ROWS, not prose: the checker's budget is what forced that, and
it was right that a scoreboard should stay a scoreboard.

Refs #213, #252

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The online-serving gate aborts on current main: harness looks for examples/server, the build produces examples/vllm-server

2 participants